package com.retail.lottery.colalottery.job.order.dealStrategy;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.retail.lottery.colalottery.constant.ColaHttpUrlConfig;
import com.retail.lottery.colalottery.entity.*;
import com.retail.lottery.colalottery.enums.*;
import com.retail.lottery.colalottery.exception.BusinessException;
import com.retail.lottery.colalottery.job.order.OrderDetailDealStrategy;
import com.retail.lottery.colalottery.mapper.CustomerAgreementInfoMapper;
import com.retail.lottery.colalottery.mapper.EffectiveGoodsMapper;
import com.retail.lottery.colalottery.mapper.WechatCustomerMapper;
import com.retail.lottery.colalottery.service.OrderCallbackService;
import com.retail.lottery.colalottery.service.OrderDetailService;
import com.retail.lottery.colalottery.service.PlatformTenantClientService;
import com.retail.lottery.colalottery.utils.RestUtils;
import com.retail.lottery.colalottery.vo.request.OrderCallBackVo;
import com.retail.lottery.colalottery.vo.request.OrderNoticeRequest;
import com.retail.lottery.colalottery.vo.response.OrderNoticeResponse;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service("mtOrderDetailDeal")
public class MtOrderDetailDealStrategy implements OrderDetailDealStrategy {

    @Resource
    private OrderCallbackService orderCallbackService;
    @Resource
    private WechatCustomerMapper wechatCustomerMapper;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private EffectiveGoodsMapper effectiveGoodsMapper;
    @Resource
    private ColaHttpUrlConfig colaHttpUrlConfig;
    @Resource
    private PlatformTenantClientService platformTenantClientService;
    @Resource
    private CustomerAgreementInfoMapper customerAgreementInfoMapper;

    @Value("${api-client-campaignCode}")
    private String lotteryCampaignCode;
    @Value("${api-client-setupId}")
    private String lotterySetupId;
    @Value("${api-bbq-client-campaignCode}")
    private String bbqCampaignCode;
    @Value("${api-bbq-client-setupId}")
    private String bbqSetupId;
    @Value("${api-client-buCode}")
    private String buCode;
    @Value("${api-callBack-mtThirdAppid}")
    private String mtThirdAppid;

    @Override
    public void dealOrderDetail(OrderCallback orderCallback, int shardingTotalCount, int shardingItem) {
        log.info("订单回调处理Job，任务总片数: {}, 当前分片项: {}，订单明细数据处理开始,orderCallback:{}", shardingTotalCount, shardingItem, orderCallback);
        // 根据orderCallback获取客户信息
        String encryptMobile = orderCallback.getEncryptMobile();
        WechatCustomer customer =
                wechatCustomerMapper.selectOne(
                        new LambdaQueryWrapper<WechatCustomer>()
                                .eq(WechatCustomer::getEncryptMobile, encryptMobile)
                                .eq(WechatCustomer::getIsDel, DeleteStatusEnum.no_del.getCode())
                                .orderByDesc(WechatCustomer::getId)             //换设备导致一个客户同一手机号对应多数据的场景，取id大值
                                .last("limit 1"));

        if (Objects.nonNull(customer)) orderCallback.setWechatCustomerId(customer.getId());

        List<OrderCallBackVo.SkuInfo> skuInfos =
                JSONObject.parseObject(
                        orderCallback.getSkuInfos(),
                        new TypeReference<List<OrderCallBackVo.SkuInfo>>() {
                        });

        int errorCount = 0;
        for (OrderCallBackVo.SkuInfo skuInfo : skuInfos) {
            OrderDetail orderDetail = orderDetailService.getBaseMapper().selectOne(new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getCallbackId, orderCallback.getId())
                    .eq(OrderDetail::getOrderCode, orderCallback.getOrderCode())
                    .eq(OrderDetail::getUpcCode, Long.valueOf(skuInfo.getUpc()))
                    .last("limit 1"));
            if (Objects.nonNull(orderDetail)) {
                log.error("订单回调处理Job，任务总片数: {}, 当前分片项: {}，订单明细数据处理-当前数据已入库,orderDetail:{}", shardingTotalCount, shardingItem, orderDetail);
                continue;
            }
            try {
                orderDetail = new OrderDetail();
                // 查询当前是否有已经insert的数据（encryptMobile + orderCode + upcCode）
                orderDetail.setCallbackId(orderCallback.getId().longValue());
                orderDetail.setEncryptMobile(encryptMobile);
                orderDetail.setOrderCode(orderCallback.getOrderCode());
                orderDetail.setActIdentifier(orderCallback.getActIdentifier());
                orderDetail.setOrderCreateTime(orderCallback.getOrderCreateTime());
                orderDetail.setOrderFinishTime(orderCallback.getOrderFinishTime());
                orderDetail.setOrderStatus(orderCallback.getOrderStatus());
                orderDetail.setSkuName(skuInfo.getName());
                orderDetail.setUpcCode(Long.valueOf(skuInfo.getUpc()));
                orderDetail.setSkuSpec(skuInfo.getSpec());
                orderDetail.setSkuNum(skuInfo.getCount());
                orderDetail.setOriginPrice(skuInfo.getOriginPrice());
                orderDetail.setActualPrice(skuInfo.getActualPrice());
                orderDetail.setTotalActualPrice(skuInfo.getTotalActualPrice());
                orderDetail.setTotalOriginPrice(skuInfo.getTotalOriginPrice());
                orderDetail.setCreateTime(new Date());
                orderDetail.setUpdateTime(new Date());
                orderDetail.setIsDel(DeleteStatusEnum.no_del.getCode());
                setOrderDetailEffective(orderDetail);
                if (Objects.isNull(customer)) {
                    log.error("订单回调处理Job，任务总片数: {}, 当前分片项: {}，订单明细数据处理失败-无对应顾客信息,orderDetail:{}", shardingTotalCount, shardingItem, orderDetail);
                    orderDetail.setDealStatus(DealStatusEnum.FAIL.getCode());
                    orderDetail.setDealMsg("无对应顾客信息");
                    errorCount++;
                } else {
                    orderDetail.setDealStatus(OrderCallbackSyncStatusEnum.SYNC_WAIT.getStatus());
                }
                orderDetailService.save(orderDetail);
            } catch (Exception e) {
                log.error("订单回调处理Job，任务总片数: {}, 当前分片项: {}，订单明细数据处理异常,orderDetail:{}", shardingTotalCount, shardingItem, orderDetail, e);
                orderDetail.setDealStatus(DealStatusEnum.FAIL.getCode());
                orderDetail.setDealMsg(e.getMessage());
                errorCount++;
            }
        }
        boolean havaError = errorCount == 0;
        orderCallback.setStatus(havaError ? OrderCallbackStatusEnum.all_ok.getCode() : OrderCallbackStatusEnum.part_ok.getCode());
        orderCallback.setSyncStatus(havaError ? OrderCallbackSyncStatusEnum.SYNC_WAIT.getStatus() : OrderCallbackSyncStatusEnum.SYNC_NO.getStatus());
        orderCallbackService.updateById(orderCallback);
        log.info("订单回调处理Job，任务总片数: {}, 当前分片项: {}，订单明细数据处理完成,orderCallback:{}", shardingTotalCount, shardingItem, orderCallback.getId());
    }

    private void setOrderDetailEffective(OrderDetail orderDetail) {
//        List<EffectiveGoods> effectiveGoods = effectiveGoodsMapper.selectList(new LambdaQueryWrapper<EffectiveGoods>()
//                //.eq(EffectiveGoods::getSetupId, orderDetail.getSetupId()) TODO 此字段待定
//                .eq(EffectiveGoods::getUpcCode, orderDetail.getUpcCode())
//                .eq(EffectiveGoods::getIsDel, DeleteStatusEnum.no_del.getCode()));
//        orderDetail.setIsEffective(CollectionUtils.isEmpty(effectiveGoods) ? 0 : 1);
        orderDetail.setIsEffective(1); //美团目前返回都是有效单

    }

    @Override
    public void syncOrderDetail(OrderCallback orderCallback,String channelType, String setupId, int shardingTotalCount, int shardingItem) {
        log.info("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，订单明细数据处理开始, orderCallback:{}", shardingTotalCount, shardingItem, orderCallback);
        try {
            //可乐订单通知接口
            //1.拼参数
            WechatCustomer wechatCustomer = wechatCustomerMapper.selectById(orderCallback.getWechatCustomerId());
            CustomerAgreementInfo customerAgreementInfo = customerAgreementInfoMapper.selectOne(new LambdaQueryWrapper<CustomerAgreementInfo>()
                    .eq(CustomerAgreementInfo::getOpenId, wechatCustomer.getOpenId())
                    .eq(CustomerAgreementInfo::getIsDel, DeleteStatusEnum.no_del.getCode())
                    .orderByDesc(CustomerAgreementInfo::getId)
                    .last("limit 1"));
            if (Objects.isNull(customerAgreementInfo)
                    || Objects.isNull(customerAgreementInfo.getAgreementStatus())
                    || AgreementStatusEnum.NOT_AGREE.getCode().equals(customerAgreementInfo.getAgreementStatus())
                    || (StringUtils.isNotBlank(customerAgreementInfo.getOneid())
                    && StringUtils.isNotBlank(wechatCustomer.getOneid())
                    && !customerAgreementInfo.getOneid().equals(wechatCustomer.getOneid()))) {
                // 抽奖活动需要抽奖协议授权--不授权不需要回传订单
                // 烧烤节--本身不需要授权流程--所以所有的订单均回传
                // 20250724 诗雅提出协议不签署，烧烤节也不回传订单，此处为订单回传业务逻辑调整点
//                if (lotterySetupId.equals(setupId)) {
                log.info("美团协议未签署订单不允许回传ocp:wechatCustomer-{},customerAgreementInfo-{}", wechatCustomer, customerAgreementInfo);
                    orderCallback.setSyncStatus(OrderCallbackSyncStatusEnum.NOT_AGREE_JOIN.getStatus());
                    //未同意协议直接返回-不推送协议
                    orderCallbackService.updateById(orderCallback);
                    return;
//                }
            }
            OrderNoticeRequest orderNoticeRequest = buildOrderNoticeRequest(orderCallback, channelType, wechatCustomer, setupId);

            //2.发请求
            String orderNoticeUrl = colaHttpUrlConfig.getOrderNoticeUrl(buCode);
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", platformTenantClientService.getAccessToken(setupId));
            // 4. 发送POST请求
            log.info("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，推送订单code:{},订单推送请求数据：{},setupId{},lotteryCampaignCode{},bbqCampaignCode{}", shardingTotalCount, shardingItem, orderCallback.getOrderCode(), JSONObject.toJSONString(orderNoticeRequest), setupId, lotteryCampaignCode, bbqCampaignCode);
            HttpResponse response = HttpRequest.post(orderNoticeUrl)
                    .headerMap(headers, true) // 添加Headers
                    .body(JSONUtil.toJsonStr(orderNoticeRequest)) // JSON参数
                    .execute();
            log.info("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，推送订单:{}，status:{},结果:{}", shardingTotalCount, shardingItem, orderCallback.getOrderCode(), response.getStatus(), JSONObject.toJSONString(response.body()));
            OrderNoticeResponse result = JSONObject.parseObject(response.body(), OrderNoticeResponse.class);
            if (result.getSuccess()) {
                log.info("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，推送OrderCode:{}，订单通知成功", shardingTotalCount, shardingItem, orderCallback.getOrderCode());
                orderCallback.setSyncStatus(OrderCallbackSyncStatusEnum.SYNC_SUCCESS.getStatus());
            } else {
                log.error("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，推送OrderCode:{}，订单通知失败", shardingTotalCount, shardingItem, orderCallback.getOrderCode());
                throw new BusinessException(ErrorCodeEnum.POST_FAIL);
            }
        } catch (Exception e) {
            log.error("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，推送OrderCode:{}，订单数据推送可乐job异常", shardingTotalCount, shardingItem, orderCallback.getOrderCode(), e);
            orderCallback.setFailNum(orderCallback.getFailNum() + 1);
            orderCallback.setFailNoticeDt(DateUtil.format(new DateTime(), "yyyyMMddHHmm"));
            orderCallback.setSyncStatus(orderCallback.getFailNum() >= 3 ? OrderCallbackSyncStatusEnum.SYNC_FAIL.getStatus() : OrderCallbackSyncStatusEnum.SYNC_AGAIN.getStatus());
        }
        //3.更新结果
        orderCallbackService.updateById(orderCallback);

        log.info("订单同步可乐Job，任务总片数: {}, 当前分片项: {}，推送OrderCode:{}，订单同步数据处理完成", shardingTotalCount, shardingItem, orderCallback.getId());
    }

    private OrderNoticeRequest buildOrderNoticeRequest(OrderCallback orderCallback, String channelType, WechatCustomer wechatCustomer, String setupId) {
        OrderNoticeRequest orderNoticeRequest = new OrderNoticeRequest();
        Long timestampInSeconds = TimeUnit.MILLISECONDS.toSeconds(orderCallback.getOrderCreateTime().getTime());
        orderNoticeRequest.setCreate_time(timestampInSeconds.intValue());
        Long finishTimestampInSeconds = TimeUnit.MILLISECONDS.toSeconds(orderCallback.getOrderFinishTime().getTime());
        orderNoticeRequest.setUpdate_time(finishTimestampInSeconds.intValue());
        orderNoticeRequest.setOrder_id(orderCallback.getOrderCode());
        orderNoticeRequest.setStatus(changeMtStatus2ColaStatus(orderCallback));
        orderNoticeRequest.setOneid(wechatCustomer.getOneid());
        orderNoticeRequest.setMobile_secret(wechatCustomer.getEncryptMobile());
        orderNoticeRequest.setChannel(channelType);
        orderNoticeRequest.setThird_appid(mtThirdAppid);
        if (lotterySetupId.equals(setupId)) {
            orderNoticeRequest.setCampaign_code(lotteryCampaignCode);
        } else if (bbqSetupId.equals(setupId)) {
            orderNoticeRequest.setCampaign_code(bbqCampaignCode);
        }
        OrderNoticeRequest.OrderDetailBean orderDetailBean = new OrderNoticeRequest.OrderDetailBean();
        List<OrderDetail> orderDetails = orderDetailService.getBaseMapper().selectList(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getCallbackId, orderCallback.getId())
                .eq(OrderDetail::getIsDel, DeleteStatusEnum.no_del.getCode()));
        List<OrderNoticeRequest.OrderDetailBean.ProductInfosBean> productInfosBeans = orderDetails.stream().map(orderDetail -> {
            OrderNoticeRequest.OrderDetailBean.ProductInfosBean productInfosBean = new OrderNoticeRequest.OrderDetailBean.ProductInfosBean();
            //productInfosBean.setProduct_id(); spuId和skuId任意传一个
            productInfosBean.setSku_id(String.valueOf(orderDetail.getUpcCode()));
            productInfosBean.setSku_cnt(orderDetail.getSkuNum());
            productInfosBean.setSale_price(Integer.valueOf(changePrice(orderDetail.getOriginPrice())));
            productInfosBean.setTitle(orderDetail.getSkuName());
            int merchant_discounted_price = Math.abs(Integer.valueOf(changePrice(orderDetail.getTotalOriginPrice())) - Integer.valueOf(changePrice(orderDetail.getTotalActualPrice())));
            productInfosBean.setIs_discounted(merchant_discounted_price > 0);
            productInfosBean.setReal_price(Integer.valueOf(changePrice(orderDetail.getTotalActualPrice())));
            productInfosBean.setMerchant_discounted_price(merchant_discounted_price);
            return productInfosBean;
        }).collect(Collectors.toList());
        OrderNoticeRequest.OrderDetailBean.PriceInfoBean priceInfoBean = new OrderNoticeRequest.OrderDetailBean.PriceInfoBean();
        priceInfoBean.setProduct_price(orderDetails.stream().mapToInt(x -> {
            return Integer.valueOf(changePrice(x.getTotalOriginPrice()));
        }).sum());
        priceInfoBean.setOrder_price(orderDetails.stream().mapToInt(x -> {
            return Integer.valueOf(changePrice(x.getTotalActualPrice()));
        }).sum());
        priceInfoBean.setDiscounted_price(Math.abs(priceInfoBean.getProduct_price() - priceInfoBean.getOrder_price()));
        orderDetailBean.setPrice_info(priceInfoBean);
        orderDetailBean.setProduct_infos(productInfosBeans);
        orderNoticeRequest.setOrder_detail(orderDetailBean);
        return orderNoticeRequest;
    }

    private Integer changeMtStatus2ColaStatus(OrderCallback orderCallback) {
        if (8 == orderCallback.getOrderStatus()) {
            return 100; //已完成
        }
        log.error("订单状态异常,orderCallback:{}", orderCallback);
        throw new BusinessException(ErrorCodeEnum.STATUS_FAIL);
    }


    private Integer changePrice(String actualPrice) {
        return Integer.valueOf(actualPrice.replace(".", ""));
    }

}
